#ifndef TARGETFINDINGCA_H
#define TARGETFINDINGCA_H


#include <vector>
#include <cstdio>
#include "ca-pathfinding/CAs/ca.h"
#include "ca-pathfinding/rules/TargetFinding.h"
#include "ca-pathfinding/neighbourhoods/moore_von_neuman3D_1.h"
#include "ca-pathfinding/grids/grid.h"



using namespace std;
using namespace tfr;

class TargetFindingCA:public CA
{


public:

    TargetFindingCA():CA()
    {
        step=0;
    }

    bool next()
    {
        bool changed=false;
        for(int i=0;i<current_states->height();++i)
            for(int j=0;j<current_states->width();++j)
            {
                if(current_states->tiles[i][j]->state==MARKED)continue;
                new_states->tiles[i][j]->state=current_states->tiles[i][j]->state;
                vector<Tile*> nbs=mvnn::neighbours(current_states,i,j);

                for(int r=0;r<RULES_SIZE;++r)
                {
                    bool f=true;
                    if(current_states->tiles[i][j]->state!=EMPTY)break;
                    for(int n=0;n<NEIGHBOURS_SIZE;++n)
                    {

                        if((rules[r][n+1]!=OCCUPIED || (nbs[n]->state!=WALL && nbs[n]->state!=OCCUPIED))&&
                                rules[r][n+1]!=ANY && nbs[n]->state!=rules[r][n+1])
                        {

                            f=false;
                            break;
                        }
                    }
                    if(f)
                    {
                        State new_state=rules[r][NEIGHBOURS_SIZE+1];
                        changed=(new_states->tiles[i][j]->state!=new_state);
                        if(changed)
                        {
                            new_states->tiles[i][j]->state=new_state;
                            //ustaw sasiadów NE,SE,SW,NW na marked
                            if(nbs[1]->state==EMPTY)new_states->tiles[i-1][j+1]->state=MARKED;
                            if(nbs[3]->state==EMPTY)new_states->tiles[i+1][j+1]->state=MARKED;
                            if(nbs[5]->state==EMPTY)new_states->tiles[i+1][j-1]->state=MARKED;
                            if(nbs[7]->state==EMPTY)new_states->tiles[i-1][j-1]->state=MARKED;
                        }
                        break;
                    }
                }
            }

        for(int i=0;i<current_states->height();++i)
            for(int j=0;j<current_states->width();++j)
                if(new_states->tiles[i][j]->state==MARKED)new_states->tiles[i][j]->state=EMPTY;

        Grid* tmp=new_states;
        new_states=current_states;
        current_states=tmp;

        ++step;
        return changed;

    }

    void start(){
        while(next());
    }

    void start(int steps)
    {
        for(int i=0;i<steps;++i)next();
    }

    int getStep()const
    {
        return step;
    }



};




#endif // TARGETFINDINGCA_H
